package com.alibaba.basic.service.impl;

import com.alibaba.basic.dto.CodeDto;
import com.alibaba.basic.exception.BusinessException;
import com.alibaba.basic.service.IVerifyCodeService;
import com.alibaba.basic.util.StrUtils;
import com.alibaba.basic.util.VerifyCodeUtils;
import com.alibaba.user.domain.User;
import com.alibaba.user.mapper.UserMapper;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.concurrent.TimeUnit;
@Service
public class VerifyCodeServiceImpl implements IVerifyCodeService {
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private UserMapper userMapper;


    @Override
    public String imageVerifyCode(String key) {
        // 调用工具类生成图形验证码
        String code = StrUtils.getComplexRandomString(4);

        // 将图形码保存到redis中， 并设置五分钟的过期时间
        redisTemplate.opsForValue().set(key,code,5, TimeUnit.MINUTES);

        // 调用工具类将图形验证码写到图上  并base64编码的字符串
        String base64Str = VerifyCodeUtils.verifyCode(100, 30, code);

        //返回base64编码的字符串
        return base64Str;
    }

    @Override
    public String phoneVerifyCode(CodeDto codeDto) {
        String phone = codeDto.getPhone();
        String inputImageCode =   codeDto.getImageCode();
        String key =  codeDto.getImageCodeKey();
        // 一.校验是否空置
        if (StringUtils.isEmpty(phone) || StringUtils.isEmpty(inputImageCode)){
            throw new BusinessException("信息不能为空");
        }
        // 二.检验手机号是否注册过
        // 从user表中查询phone
         User user = userMapper.findByPhone(phone);
        if (user !=null){// 表示手机号已经注册过
            throw new BusinessException("手机号已经注册过，请直接登录");
        }
        // 三.校验图形验证码是否过期 ---并且是否正确
        Object redisImageCode = redisTemplate.opsForValue().get(key);
        if (redisImageCode ==null){
            throw new BusinessException("图形验证码已经过期");
        }
        if (!inputImageCode.equalsIgnoreCase(redisImageCode.toString())){
            throw new BusinessException("图形验证码输入不正确");
        }
        //四：直接从redis获取手机验证码
        Object phoneCode = redisTemplate.opsForValue().get("register:" + phone);
        //1.没有获取到 = 第一次发送或者过期了，调用StrUtils工具类重新生成
        String code = null;  //用于保存手机验证码
        if(phoneCode == null){
            code = StrUtils.getRandomString(4);//4位纯数字的验证码
        }else{
            //2.获取到了 = 没有过期，判断重发时间【时间戳 】
            Long oldTime = Long.parseLong(phoneCode.toString().split(":")[1]); //之前的验证码设置的时间戳
            if((System.currentTimeMillis() - oldTime)<1*60*1000){ //1分钟重发时间
                //a.如果没有过重发时间 - 没有重发时间，居然发请求过了 = 违规操作 - 抛异
                throw new BusinessException("操作频繁，稍后重试!!!");
            }else{
                //b.如果过了重发时间 - 可以获取新的验证码【用没有过期的 - code:时间戳】
                code = phoneCode.toString().split(":")[0];
            }
        }

        // 五. 将key和验证码保存到redis中
        redisTemplate.opsForValue().set("register:" + phone,code+":"+System.currentTimeMillis(),3,TimeUnit.MINUTES);
        // 六.调用短信接口发送短信
//        SmsUtils.sendSms(phone,"你的手机验证码是"+ code + "请收到验证码3分钟类使用");
        System.out.println("你的手机验证码是:"+ code + ":请收到验证码3分钟类使用");

        return null;
    }

    @Override
    public void binderVerifyCode(CodeDto codeDto) { String phone = codeDto.getPhone();
        //一：校验：空值校验 - 前端和后端都可以校验手机格式问题
        if(StringUtils.isEmpty(phone)){
            throw new BusinessException("信息不能为空!!!");
        }

        //三：校验：手机号码是否注册过
        //两个微信不能绑定一个手机号
        User user = userMapper.findWxUserByPhone(phone);
        if(user != null){//根据手机号码查到了 = 手机已经注册
            throw new BusinessException("该号码已经绑定过不能重复绑定，请直接登陆!!!");
        }

        //四：直接从redis获取手机验证码：key【业务🗡:手机号】
        Object phoneCode = redisTemplate.opsForValue().get("binder:" + phone);
        //1.没有获取到 = 第一次发送或者过期了，调用StrUtils工具类重新生成
        String code = null;//用于保存手机验证码
        if(phoneCode == null){
            code = StrUtils.getRandomString(4);//4位纯数字的验证码
        }else{
            //2.获取到了 = 没有过期，判断重发时间【时间戳 】
            Long oldTime = Long.parseLong(phoneCode.toString().split(":")[1]); //之前的验证码设置的时间戳
            if((System.currentTimeMillis() - oldTime)<1*60*1000){ //1分钟重发时间
                //a.如果没有过重发时间 - 没有重发时间，居然发请求过了 = 违规操作 - 抛异
                throw new BusinessException("操作频繁，稍后重试!!!");
            }else{
                //b.如果过了重发时间 - 可以获取新的验证码【用没有过期的 - code:时间戳】
                code = phoneCode.toString().split(":")[0];
            }
        }

        //五：讲key和验证码保存在redis，重新设置过期时间3分钟【如果是用以前的-这句话就刷新了过期时间】
        redisTemplate.opsForValue().set("binder:" + phone,code+":"+System.currentTimeMillis(),3,TimeUnit.MINUTES);
        //六：调用短信的工具类发送短信
        //SmsUtils.sendSms(phone,"你的手机验证码是：" + code +",请在3分钟内使用!!!");
        System.out.println("你的手机验证码是：" + code +",请在3分钟内使用!!!");

    }
}
